#!/usr/bin/env python3
# coding: utf-8
# File: causality_pattern.py


import re
import jieba.posseg as pseg
from pyltp import SentenceSplitter
class CausalityExractor():
    def __init__(self):
        pass

    '''1由果溯因配套式'''
    def ruler1(self, sentence):
        '''
        conm2:〈[之]所以,因为〉、〈[之]所以,由于〉、 <[之]所以,缘于〉
        conm2_model:<Conj>{Effect},<Conj>{Cause}
        '''
        datas = list()
        word_pairs =[['之?所以', '因为'], ['之?所以', '由于'], ['之?所以', '缘于']]
        for word in word_pairs:
            pattern = re.compile(r'\s?(%s)/[p|c]+\s(.*)(%s)/[p|c]+\s(.*)' % (word[0], word[1]))
            result = pattern.findall(sentence)
            data = dict()
            if result:
                data['tag'] = result[0][0] + '-' + result[0][2]
                data['cause'] = result[0][3]
                data['effect'] = result[0][1]
                datas.append(data)
        if datas:
            return datas[0]
        else:
            return {}
    '''2由因到果配套式'''
    def ruler2(self, sentence):
        '''
        conm1:〈因为,从而〉、〈因为,为此〉、〈既[然],所以〉、〈因为,为此〉、〈由于,为此〉、〈只有|除非,才〉、〈由于,以至[于]>、〈既[然],却>、
        〈如果,那么|则〉、<由于,从而〉、<既[然],就〉、〈既[然],因此〉、〈如果,就〉、〈只要,就〉〈因为,所以〉、 <由于,于是〉、〈因为,因此〉、
         <由于,故〉、 〈因为,以致[于]〉、〈因为,因而〉、〈由于,因此〉、<因为,于是〉、〈由于,致使〉、〈因为,致使〉、〈由于,以致[于] >
         〈因为,故〉、〈因[为],以至[于]>,〈由于,所以〉、〈因为,故而〉、〈由于,因而〉
        conm1_model:<Conj>{Cause}, <Conj>{Effect}
        '''
        datas = list()
        word_pairs =[['因为', '从而'], ['因为', '为此'], ['既然?', '所以'],
                    ['因为', '为此'], ['由于', '为此'], ['除非', '才'],
                    ['只有', '才'], ['由于', '以至于?'], ['既然?', '却'],
                    ['如果', '那么'], ['如果', '则'], ['由于', '从而'],
                    ['既然?', '就'], ['既然?', '因此'], ['如果', '就'],
                    ['只要', '就'], ['因为', '所以'], ['由于', '于是'],
                    ['因为', '因此'], ['由于', '故'], ['因为', '以致于?'],
                    ['因为', '以致'], ['因为', '因而'], ['由于', '因此'],
                    ['因为', '于是'], ['由于', '致使'], ['因为', '致使'],
                    ['由于', '以致于?'], ['因为', '故'], ['因为?', '以至于?'],
                    ['由于', '所以'], ['因为', '故而'], ['由于', '因而']]

        for word in word_pairs:
            pattern = re.compile(r'\s?(%s)/[p|c]+\s(.*)(%s)/[p|c]+\s(.*)' % (word[0], word[1]))
            result = pattern.findall(sentence)
            data = dict()
            if result:
                data['tag'] = result[0][0] + '-' + result[0][2]
                data['cause'] = result[0][1]
                data['effect'] = result[0][3]
                datas.append(data)
        if datas:
            return datas[0]
        else:
            return {}
    '''3由因到果居中式明确'''
    def ruler3(self, sentence):
        '''
        cons2:于是、所以、故、致使、以致[于]、因此、以至[于]、从而、因而
        cons2_model:{Cause},<Conj...>{Effect}
        '''

        pattern = re.compile(r'(.*)[,，]+.*(于是|所以|故|致使|以致于?|因此|以至于?|从而|因而)/[p|c]+\s(.*)')
        result = pattern.findall(sentence)
        data = dict()
        if result:
            data['tag'] = result[0][1]
            data['cause'] = result[0][0]
            data['effect'] = result[0][2]
        return data
    '''4由因到果居中式精确'''
    def ruler4(self, sentence):
        '''
        verb1:牵动、导向、使动、导致、勾起、引入、指引、使、予以、产生、促成、造成、引导、造就、促使、酿成、
            引发、渗透、促进、引起、诱导、引来、促发、引致、诱发、推进、诱致、推动、招致、影响、致使、滋生、归于、
            作用、使得、决定、攸关、令人、引出、浸染、带来、挟带、触发、关系、渗入、诱惑、波及、诱使
        verb1_model:{Cause},<Verb|Adverb...>{Effect}
        '''
        pattern = re.compile(r'(.*)\s+(牵动|已致|导向|使动|导致|勾起|引入|指引|使|予以|产生|促成|造成|引导|造就|促使|酿成|引发|渗透|促进|引起|诱导|引来|促发|引致|诱发|推进|诱致|推动|招致|影响|致使|滋生|归于|作用|使得|决定|攸关|令人|引出|浸染|带来|挟带|触发|关系|渗入|诱惑|波及|诱使)/[d|v]+\s(.*)')
        result = pattern.findall(sentence)
        data = dict()
        if result:
            data['tag'] = result[0][1]
            data['cause'] = result[0][0]
            data['effect'] = result[0][2]
        return data
    '''5由因到果前端式模糊'''
    def ruler5(self, sentence):
        '''
        prep:为了、依据、为、按照、因[为]、按、依赖、照、比、凭借、由于
        prep_model:<Prep...>{Cause},{Effect}
        '''
        pattern = re.compile(r'\s?(为了|依据|按照|因为|因|按|依赖|凭借|由于)/[p|c]+\s(.*)[,，]+(.*)')
        result = pattern.findall(sentence)
        data = dict()
        if result:
            data['tag'] = result[0][0]
            data['cause'] = result[0][1]
            data['effect'] = result[0][2]

        return data

    '''6由因到果居中式模糊'''
    def ruler6(self, sentence):
        '''
        adverb:以免、以便、为此、才
        adverb_model:{Cause},<Verb|Adverb...>{Effect}
        '''
        pattern = re.compile(r'(.*)(以免|以便|为此|才)\s(.*)')
        result = pattern.findall(sentence)
        data = dict()
        if result:
            data['tag'] = result[0][1]
            data['cause'] = result[0][0]
            data['effect'] = result[0][2]
        return data

    '''7由因到果前端式精确'''
    def ruler7(self, sentence):
        '''
        cons1:既[然]、因[为]、如果、由于、只要
        cons1_model:<Conj...>{Cause},{Effect}
        '''
        pattern = re.compile(r'\s?(既然?|因|因为|如果|由于|只要)/[p|c]+\s(.*)[,，]+(.*)')
        result = pattern.findall(sentence)
        data = dict()
        if result:
            data['tag'] = result[0][0]
            data['cause'] = result[0][1]
            data['effect'] = result[0][2]
        return data
    '''8由果溯因居中式模糊'''
    def ruler8(self, sentence):
        '''
        3
        verb2:根源于、取决、来源于、出于、取决于、缘于、在于、出自、起源于、来自、发源于、发自、源于、根源于、立足[于]
        verb2_model:{Effect}<Prep...>{Cause}
        '''

        pattern = re.compile(r'(.*)(根源于|取决|来源于|出于|取决于|缘于|在于|出自|起源于|来自|发源于|发自|源于|根源于|立足|立足于)/[p|c]+\s(.*)')
        result = pattern.findall(sentence)
        data = dict()
        if result:
            data['tag'] = result[0][1]
            data['cause'] = result[0][2]
            data['effect'] = result[0][0]
        return data
    '''9由果溯因居端式精确'''
    def ruler9(self, sentence):
        '''
        cons3:因为、由于
        cons3_model:{Effect}<Conj...>{Cause}
        '''
        pattern = re.compile(r'(.*)是?\s(因为|由于)/[p|c]+\s(.*)')
        result = pattern.findall(sentence)
        data = dict()
        if result:
            data['tag'] = result[0][1]
            data['cause'] = result[0][2]
            data['effect'] = result[0][0]

        return data

    '''抽取主函数'''
    def extract_triples(self, sentence):
        infos = list()
      #  print(sentence)
        if self.ruler1(sentence):
            infos.append(self.ruler1(sentence))
        elif self.ruler2(sentence):
            infos.append(self.ruler2(sentence))
        elif self.ruler3(sentence):
            infos.append(self.ruler3(sentence))
        elif self.ruler4(sentence):
            infos.append(self.ruler4(sentence))
        elif self.ruler5(sentence):
            infos.append(self.ruler5(sentence))
        elif self.ruler6(sentence):
            infos.append(self.ruler6(sentence))
        elif self.ruler7(sentence):
            infos.append(self.ruler7(sentence))
        elif self.ruler8(sentence):
            infos.append(self.ruler8(sentence))
        elif self.ruler9(sentence):
            infos.append(self.ruler9(sentence))

        return infos

    '''抽取主控函数'''
    def extract_main(self, content):
        sentences = self.process_content(content)
        datas = list()
        for sentence in sentences:
            subsents = self.fined_sentence(sentence)
            subsents.append(sentence)
            for sent in subsents:
                sent = ' '.join([word.word + '/' + word.flag for word in pseg.cut(sent)])
                result = self.extract_triples(sent)
                if result:
                    for data in result:
                        if data['tag'] and data['cause'] and data['effect']:
                            datas.append(data)
        return datas

    '''文章分句处理'''
    def process_content(self, content):
        return [sentence for sentence in SentenceSplitter.split(content) if sentence]

    '''切分最小句'''
    def fined_sentence(self, sentence):
        return re.split(r'[？！，；]', sentence)


'''测试'''
def test():

    content1 = '''谈到美国打了20年之久的阿富汗战争，人们不由得会做一个对比：当年的越南战争创下二战结束以来美国对外战争伤亡人数之最，阿富汗战争则是创造了持续时间之最。越南战争结束后给美国留下深刻的越南战争后遗症，现在美国士兵虽已全部从阿富汗撤出，但阿富汗战争后遗症将会在美国社会持续发酵。

相比越南战争给美国留下的战后创伤后遗症，这场耗时20年、伤亡美军2万多人、花费美国纳税人2.3万亿美元的阿富汗战争留给美国的后遗症，无论在人们心理健康、社会意识乃至国内政治争斗中，都将产生广泛而持续的影响。这种影响将如何发展，现在下判断还为时过早，但可以确定的是，美国不会从彻底失败的阿富汗战争中吸取教训。


北京时间8月31日，美国国防部在推特上公布了最后一名撤离阿富汗的美国军人照片。

我们要认识到，阿富汗撤军和越南撤军的形式与实质都不一样。形式上，从南越撤出标志着美国在南越军事存在的彻底离开，阿富汗撤军则是美国军队撤出了，但它的军事存在依然会延续，具体表现为它还会对阿富汗进行无人机打击，以及必要时美军战略轰炸机也会出现。实质上，南越撤军是美国彻底撒手，阿富汗撤军呢，美国想要彻底撒手是不可能的。


笔者认为，美国从阿富汗彻底撤军，是关上了一扇“止损”的门，却打开了四扇麻烦之窗。它们分别是，与经济崩溃伴生的人道主义危机、恐怖主义的东山再起、潜在的难民潮和内战重燃。这四扇窗打开后的影响将很快外溢到阿富汗之外，并深刻影响美国的内政与外交，对美国来说，这将会比越南战争后遗症麻烦得多。

可以预见，阿富汗局势接下来每一步变化都将引发美国国内更长期的激烈争吵，尤其是恐怖袭击的问题。就在“8·26喀布尔机场恐袭事件”之前，一些民主党人还一直辩解说，虽然这20年美国没有赢得什么，但毕竟为美国本土赢来20年的平静，但8月26日恐袭事件让这一辩解变得苍白无力。由于美国国内的政治正确，以后只要阿富汗出现恐怖袭击，美国政府就会报复，由此出现一个逐步升级的恶性循环。

对此，美国人是不会吸取教训的。从朝鲜战争到越南战争，从伊拉克战争再到阿富汗战争，美国从来没有认真吸取过教训。对于阿富汗战争，美国的教训在于一个非常简单的问题：它花了20年时间究竟在干什么。当年美国打入阿富汗的最直接目的是要让塔利班交出本·拉登，时任总统小布什说这是反恐战争的一部分，但是美国实际做的跟它当初的“理由”从来都不一致。

阿富汗战争的结果是越反越恐。阿富汗战争之前，境内恐怖组织有5个，现在美国撤军的时候有据可查的恐怖组织就有20多个，以至于美国撤军的时候立马就能给它一点颜色看看。这样的结果进一步证明美国的阿富汗战争是失败的。实际上，美军这20年在阿富汗从事的并不是反恐战争，除了前几个月是跟塔利班在打，之后绝大部分时间打的都是治安战。美国之所以不远万里去阿富汗打治安战，为的就是要按照美国理想的民主体制重塑阿富汗的政治体系。然而，花了2.3万亿美元后，美国竹篮打水一场空。就像中俄外长都提到的，不顾一个地区几百年传统和文化的现实，去移植一个非本土的体制是不可能成功的。

美国人不会吸取这个教训，因为这涉及到它根本的自信，涉及到基督教传统教义和文化，因此只能说，今后类似的教训美国还会继续积累。但是，阿富汗战争后遗症的存在是客观现实，这是美国回避不了的，它会向美国的对外战争、对外政策提出一系列难以回答的问题和悖论，对美国未来的对外政策具有拐点意义。

在阿富汗战争打开的四扇灾难之窗中，美国很难独善其身，尤其是恐怖主义的东山再起，是美国无论如何也逃避不了的。接下来，华盛顿会陷入一个棘手的境地，从“9·11”之后到特朗普之前，美国在将近17年的时间里走的是应对非传统国家安全的战略轨道，把反恐作为国家安全首要目标，而不把大国竞争作为第一要务。特朗普上台后，直到现在拜登政府的整个国家安全战略则是重新转向大国竞争，避免一切实力接近的力量超过自己。但是现在华盛顿发现，不管它如何渲染中俄的威胁，现实中真正给美国造成最直接和最紧迫安全威胁的，是恐怖主义、气候变化这类非传统安全领域的威胁。这就使得美国的国家大战略深陷一种传统理念和现实生存之间的矛盾困境：基于大国竞争的传统理念，美国必须把中国、俄罗斯等大国作为首要安全威胁，而非传统领域的恐怖主义、气候变化等挑战，却在每时每刻威胁着美国的生存安全。

那么美国有限的资源应该聚焦在哪个轨道上？一些美国原教旨的战略分子会认为，不管恐怖分子多危险，无论气候变化的危机多么紧迫，美国的战略资源投入必须聚焦美国同中俄的大国竞争。在撤军阿富汗之后，美国应该怎样重新配置自己有限的战略资源投入？是应对现实生存安全威胁第一，还是打压传统理念的假想敌大国至上？这一棘手的难题将不仅是理论上的战略争论，更是一个现实上的战略抉择。（作者是中国国际问题研究院研究员）
    '''
    extractor = CausalityExractor()
    datas = extractor.extract_main(content1)
    print(datas)
    for data in datas:
        print('******'*4)
        print('cause', ''.join([word.split('/')[0] for word in data['cause'].split(' ') if word.split('/')[0]]))
        print('tag', data['tag'])
        print('effect', ''.join([word.split('/')[0] for word in data['effect'].split(' ') if word.split('/')[0]]))

test()
